/*     */ package com.zimbra.cs.octosync.store;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import com.zimbra.cs.store.Blob;
/*     */ import com.zimbra.cs.store.IncomingBlob;
/*     */ import com.zimbra.cs.store.StoreManager;
/*     */ import com.zimbra.cs.store.StoreManager.StoreFeature;
/*     */ import com.zimbra.cs.store.external.SisStore;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.HashMap;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.Timer;
/*     */ import java.util.TimerTask;
/*     */ import java.util.TreeMap;
/*     */ import java.util.UUID;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class StoreManagerBasedTempBlobStore
/*     */   extends BlobStore
/*     */ {
/*  58 */   private static final Log log = LogFactory.getLog(StoreManagerBasedTempBlobStore.class);
/*     */   
/*     */ 
/*     */ 
/*     */   private StoreManager storeManager;
/*     */   
/*     */ 
/*     */   private boolean storedCached;
/*     */   
/*     */ 
/*     */   private Map<String, IncomingBlob> incomingBlobs;
/*     */   
/*     */ 
/*     */   private Map<String, TreeMap<Integer, StoredBlob>> storedBlobs;
/*     */   
/*     */ 
/*     */   private long incomingExpiration;
/*     */   
/*     */ 
/*     */   private long storedExpiration;
/*     */   
/*     */ 
/*     */   private static final long REAPER_INTERVAL_MSEC = 180000L;
/*     */   
/*     */ 
/*     */ 
/*     */   public final class StoredBlob
/*     */     extends BlobStore.StoredBlob
/*     */   {
/*     */     private Object ctx;
/*     */     
/*     */ 
/*     */     private long lastAccessTime;
/*     */     
/*     */ 
/*     */     private long size;
/*     */     
/*     */ 
/*     */ 
/*     */     protected StoredBlob(String id, Blob blob, Object ctx, long size)
/*     */     {
/*  99 */       super(id, blob);
/* 100 */       this.ctx = ctx;
/* 101 */       this.size = size;
/* 102 */       this.lastAccessTime = System.currentTimeMillis();
/*     */     }
/*     */     
/*     */     public InputStream getInputStream()
/*     */       throws IOException
/*     */     {
/* 108 */       this.lastAccessTime = System.currentTimeMillis();
/* 109 */       return this.blob.getInputStream();
/*     */     }
/*     */     
/*     */ 
/*     */     public Object getContext()
/*     */     {
/* 115 */       return this.ctx;
/*     */     }
/*     */     
/*     */ 
/*     */     public void setContext(Object value)
/*     */     {
/* 121 */       this.ctx = value;
/*     */     }
/*     */     
/*     */     private long getLastAccessTime()
/*     */     {
/* 126 */       return this.lastAccessTime;
/*     */     }
/*     */     
/*     */ 
/*     */     public long getSize()
/*     */     {
/* 132 */       return this.size;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public StoreManagerBasedTempBlobStore(StoreManager storeManager, long incomingExpiration, long storedExpiration, boolean storedCached)
/*     */   {
/* 150 */     this.storeManager = storeManager;
/* 151 */     this.incomingBlobs = new HashMap();
/* 152 */     this.storedBlobs = new HashMap();
/* 153 */     this.incomingExpiration = incomingExpiration;
/* 154 */     this.storedExpiration = storedExpiration;
/* 155 */     this.storedCached = storedCached;
/* 156 */     Zimbra.sTimer.schedule(new ReaperTask(null), 180000L, 180000L);
/*     */   }
/*     */   
/*     */ 
/*     */   public IncomingBlob createIncoming(Object ctx)
/*     */     throws IOException, ServiceException
/*     */   {
/* 163 */     synchronized (this.incomingBlobs)
/*     */     {
/*     */       String id;
/*     */       do
/*     */       {
/* 168 */         id = UUID.randomUUID().toString();
/* 169 */       } while (this.incomingBlobs.containsKey(id));
/*     */       
/* 171 */       IncomingBlob ib = this.storeManager.newIncomingBlob(id, ctx);
/*     */       
/* 173 */       this.incomingBlobs.put(id, ib);
/* 174 */       return ib;
/*     */     }
/*     */   }
/*     */   
/*     */   /* Error */
/*     */   public IncomingBlob getIncoming(String id)
/*     */   {
/*     */     // Byte code:
/*     */     //   0: aload_0
/*     */     //   1: getfield 6	com/zimbra/cs/octosync/store/StoreManagerBasedTempBlobStore:incomingBlobs	Ljava/util/Map;
/*     */     //   4: dup
/*     */     //   5: astore_2
/*     */     //   6: monitorenter
/*     */     //   7: aload_0
/*     */     //   8: getfield 6	com/zimbra/cs/octosync/store/StoreManagerBasedTempBlobStore:incomingBlobs	Ljava/util/Map;
/*     */     //   11: aload_1
/*     */     //   12: invokeinterface 22 2 0
/*     */     //   17: checkcast 23	com/zimbra/cs/store/IncomingBlob
/*     */     //   20: aload_2
/*     */     //   21: monitorexit
/*     */     //   22: areturn
/*     */     //   23: astore_3
/*     */     //   24: aload_2
/*     */     //   25: monitorexit
/*     */     //   26: aload_3
/*     */     //   27: athrow
/*     */     // Line number table:
/*     */     //   Java source line #182	-> byte code offset #0
/*     */     //   Java source line #183	-> byte code offset #7
/*     */     //   Java source line #184	-> byte code offset #23
/*     */     // Local variable table:
/*     */     //   start	length	slot	name	signature
/*     */     //   0	28	0	this	StoreManagerBasedTempBlobStore
/*     */     //   0	28	1	id	String
/*     */     //   5	20	2	Ljava/lang/Object;	Object
/*     */     //   23	4	3	localObject1	Object
/*     */     // Exception table:
/*     */     //   from	to	target	type
/*     */     //   7	22	23	finally
/*     */     //   23	26	23	finally
/*     */   }
/*     */   
/*     */   public StoredBlob store(IncomingBlob ib, String id, int version)
/*     */     throws IOException, ServiceException
/*     */   {
/* 191 */     IncomingBlob myIb = ib;
/*     */     
/* 193 */     synchronized (this.incomingBlobs) {
/* 194 */       IncomingBlob existingBlob = (IncomingBlob)this.incomingBlobs.remove(myIb.getId());
/* 195 */       if (existingBlob == null)
/*     */       {
/*     */ 
/*     */ 
/* 199 */         throw ServiceException.INVALID_REQUEST("Cannot accept incoming blob " + myIb.getId(), null);
/*     */       }
/* 201 */       if ((!$assertionsDisabled) && (existingBlob != myIb)) { throw new AssertionError("Wrong blob removed: " + myIb.getId());
/*     */       }
/*     */     }
/* 204 */     Blob blob = myIb.getBlob();
/* 205 */     StoredBlob sb = new StoredBlob(id, blob, myIb.getContext(), blob.getRawSize());
/* 206 */     if (this.storedCached) {
/* 207 */       synchronized (this.storedBlobs) {
/* 208 */         TreeMap<Integer, StoredBlob> versionMap = (TreeMap)this.storedBlobs.get(id);
/*     */         
/* 210 */         if (versionMap == null) {
/* 211 */           versionMap = new TreeMap();
/* 212 */           this.storedBlobs.put(id, versionMap);
/*     */         }
/*     */         
/* 215 */         Integer versionInt = Integer.valueOf(version);
/* 216 */         assert (!versionMap.containsKey(versionInt)) : ("Version " + version + " already exists");
/*     */         
/* 218 */         versionMap.put(versionInt, sb);
/*     */       }
/*     */     }
/*     */     
/* 222 */     return sb;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public void deleteIncoming(IncomingBlob ib)
/*     */   {
/* 229 */     IncomingBlob myIb = ib;
/*     */     
/* 231 */     synchronized (this.incomingBlobs) {
/* 232 */       IncomingBlob existingBlob = (IncomingBlob)this.incomingBlobs.remove(myIb.getId());
/* 233 */       if ((!$assertionsDisabled) && (existingBlob != null) && (existingBlob != myIb)) { throw new AssertionError("Wrong blob removed: " + myIb.getId());
/*     */       }
/*     */     }
/* 236 */     myIb.cancel();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public StoredBlob get(String id)
/*     */   {
/* 243 */     synchronized (this.storedBlobs) {
/* 244 */       TreeMap<Integer, StoredBlob> versionMap = (TreeMap)this.storedBlobs.get(id);
/*     */       
/* 246 */       if ((versionMap == null) || (versionMap.isEmpty())) {
/* 247 */         return null;
/*     */       }
/*     */       
/* 250 */       return (StoredBlob)versionMap.lastEntry().getValue();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public StoredBlob get(String id, int version)
/*     */   {
/* 258 */     synchronized (this.storedBlobs) {
/* 259 */       TreeMap<Integer, StoredBlob> versionMap = (TreeMap)this.storedBlobs.get(id);
/*     */       
/* 261 */       if ((versionMap == null) || (versionMap.isEmpty())) {
/* 262 */         return null;
/*     */       }
/*     */       
/* 265 */       return (StoredBlob)versionMap.get(Integer.valueOf(version));
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public void delete(BlobStore.StoredBlob sb)
/*     */   {
/* 273 */     if (sb != null)
/*     */     {
/*     */       TreeMap<Integer, StoredBlob> versionMap;
/* 276 */       synchronized (this.storedBlobs) {
/* 277 */         versionMap = (TreeMap)this.storedBlobs.remove(sb.getId());
/*     */       }
/*     */       
/* 280 */       if (versionMap != null) {
/* 281 */         for (StoredBlob b : versionMap.values()) {
/* 282 */           this.storeManager.quietDelete(b.blob);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public void delete(BlobStore.StoredBlob sb, int version)
/*     */   {
/* 291 */     if (sb != null)
/*     */     {
/* 293 */       StoredBlob mySb = (StoredBlob)sb;
/* 294 */       String id = mySb.getId();
/*     */       
/* 296 */       synchronized (this.storedBlobs) {
/* 297 */         TreeMap<Integer, StoredBlob> versionMap = (TreeMap)this.storedBlobs.get(id);
/*     */         
/* 299 */         if (versionMap == null) {
/* 300 */           return;
/*     */         }
/*     */         
/* 303 */         StoredBlob removedSb = (StoredBlob)versionMap.remove(Integer.valueOf(version));
/*     */         
/* 305 */         if (removedSb != null)
/*     */         {
/* 307 */           assert (mySb == removedSb) : "Wrong blob removed";
/*     */           
/* 309 */           this.storeManager.quietDelete(mySb.blob);
/*     */           
/* 311 */           if (versionMap.isEmpty()) {
/* 312 */             this.storedBlobs.remove(id);
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private final class ReaperTask extends TimerTask
/*     */   {
/*     */     private ReaperTask() {}
/*     */     
/*     */     public void run()
/*     */     {
/*     */       try {
/* 326 */         ArrayList<Blob> reapedBlobs = new ArrayList();
/*     */         
/* 328 */         if (StoreManagerBasedTempBlobStore.this.incomingExpiration > 0L) { long cutoffTime;
/* 329 */           synchronized (StoreManagerBasedTempBlobStore.this.incomingBlobs)
/*     */           {
/* 331 */             cutoffTime = System.currentTimeMillis() - StoreManagerBasedTempBlobStore.this.incomingExpiration;
/*     */             
/* 333 */             for (IncomingBlob ib : StoreManagerBasedTempBlobStore.this.incomingBlobs.values()) {
/* 334 */               if (ib.getLastAccessTime() <= cutoffTime) {
/* 335 */                 ib.cancel();
/* 336 */                 StoreManagerBasedTempBlobStore.this.incomingBlobs.remove(ib.getId());
/*     */               }
/*     */             }
/*     */           }
/*     */         }
/*     */         
/* 342 */         int numReapedIncoming = reapedBlobs.size();
/*     */         
/* 344 */         if (numReapedIncoming > 0) {
/* 345 */           StoreManagerBasedTempBlobStore.log.info("Removed " + numReapedIncoming + " expired incoming incomplete blobs");
/*     */         }
/*     */         
/* 348 */         if ((StoreManagerBasedTempBlobStore.this.storedCached) && (StoreManagerBasedTempBlobStore.this.storedExpiration > 0L)) { long cutoffTime;
/* 349 */           synchronized (StoreManagerBasedTempBlobStore.this.storedBlobs)
/*     */           {
/* 351 */             cutoffTime = System.currentTimeMillis() - StoreManagerBasedTempBlobStore.this.storedExpiration;
/*     */             
/* 353 */             for (Object versionMap : StoreManagerBasedTempBlobStore.this.storedBlobs.values())
/*     */             {
/* 355 */               String sbId = null;
/*     */               
/* 357 */               for (Map.Entry<Integer, StoreManagerBasedTempBlobStore.StoredBlob> entry : ((Map)versionMap).entrySet())
/*     */               {
/* 359 */                 StoreManagerBasedTempBlobStore.StoredBlob sb = (StoreManagerBasedTempBlobStore.StoredBlob)entry.getValue();
/* 360 */                 if (StoreManagerBasedTempBlobStore.StoredBlob.access$700(sb) <= cutoffTime) {
/* 361 */                   sbId = sb.getId();
/* 362 */                   reapedBlobs.add(sb.blob);
/* 363 */                   ((Map)versionMap).remove(entry.getKey());
/*     */                 }
/*     */               }
/*     */               
/* 367 */               if ((sbId != null) && (((Map)versionMap).isEmpty())) {
/* 368 */                 Object removed = StoreManagerBasedTempBlobStore.this.storedBlobs.remove(sbId);
/* 369 */                 assert (removed == versionMap);
/*     */               }
/*     */             }
/*     */           }
/*     */         }
/*     */         
/* 375 */         int numReapedStored = reapedBlobs.size() - numReapedIncoming;
/*     */         
/* 377 */         if (numReapedStored > 0) {
/* 378 */           StoreManagerBasedTempBlobStore.log.info("Removed " + numReapedStored + " expired stored blobs");
/*     */         }
/*     */         
/* 381 */         for (Blob b : reapedBlobs) {
/* 382 */           StoreManagerBasedTempBlobStore.this.storeManager.quietDelete(b);
/*     */         }
/*     */       }
/*     */       catch (Throwable t) {
/* 386 */         StoreManagerBasedTempBlobStore.log.warn("Exception in " + getClass().getName() + ": " + t);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public boolean supportsSisCreate()
/*     */   {
/* 393 */     return this.storeManager.supports(StoreManager.StoreFeature.SINGLE_INSTANCE_SERVER_CREATE);
/*     */   }
/*     */   
/*     */   public StoredBlob getSisBlob(byte[] hash) throws IOException, ServiceException
/*     */   {
/* 398 */     SisStore sisStore = (SisStore)this.storeManager;
/* 399 */     Blob blob = sisStore.getSisBlob(hash);
/* 400 */     if (blob != null)
/*     */     {
/*     */ 
/*     */ 
/* 404 */       return new StoredBlob("", blob, null, blob.getRawSize());
/*     */     }
/* 406 */     return null;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/octosync/store/StoreManagerBasedTempBlobStore.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */